package com.fingard.dsp.bank.directbank.jrtt01;

import java.sql.Connection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IForeignCurrencyCJ;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.frgcurrsingle.*;
import com.fingard.dsp.bank.reqrespobj.frgcurrsingle.detail.CJFrgCurrSingleDetail;
import com.fingard.dsp.bank.reqrespobj.frgcurrsingle.detail.RetAtsCJFrgCurrSingleDetail;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

/**
 * 财经-海外接口
 */
public class JRTT01ForeignCurrencyCJ extends JRTT01Base implements IForeignCurrencyCJ {

    private static final String INSERTSEQ = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,BANKREQSEQID) values (?,?,?,?,?);";
    private static final String SELECTSEQ = "SELECT BANKREQSEQID FROM REQSEQIDMAPPING WHERE REQSEQID=? AND BANKCODE=?;";
    private static final String SELECTSEQ2 = "SELECT REQSEQID FROM REQSEQIDMAPPING WHERE BANKREQSEQID=? AND BANKCODE=?;";

    /**
     * 付款
     * @param reqCJFrgCurrSingleBat
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsBatPayRec foreignCurrPayCJ_BAT(ReqCJFrgCurrSingleBat reqCJFrgCurrSingleBat) throws Exception {
        //返回ATS的对象
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(reqCJFrgCurrSingleBat.reqHeader);
        //开启数据库，记录当是CITI-WL-RUB时，做流水号映射
        Connection conn= FGBiz.getLocalDbConn();
        try{
            //非公有参数
            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            //拼接请求报文头
            JRTT01Header header=new JRTT01Header();
            header.requestType="execute.001.001.03";//交易码
            header.msgId=getQryTransID();
            writeCommonHeader(xmlTextWriter,header);
            //唯一流水号
            xmlTextWriter.writeElementStringWithoutTransfer("GroupId",reqCJFrgCurrSingleBat.reqBatchNO);
            //交易金额
            xmlTextWriter.writeElementStringWithoutTransfer("TotalAmount",reqCJFrgCurrSingleBat.totalAmt);
            xmlTextWriter.writeElementStringWithoutTransfer("TotalCount",reqCJFrgCurrSingleBat.totalNum);
            xmlTextWriter.writeEndElement();
            xmlTextWriter.writeStartElement("ReqDetail");
            //拼接请求报文体
            int count=0;//统计数量
            while (reqCJFrgCurrSingleBat.readRecord()) {
                CJFrgCurrSingleDetail tmpDetail = reqCJFrgCurrSingleBat.readedDetail;
                if(StringHelper.hasAnyChar(tmpDetail.name) && StringHelper.hasAnyChar(tmpDetail.value)){
                    //================付款流水号处理start================
                    String askNumber="";//唯一请求流水号
                    Map<String, Object> selMap=JDBCHelper.execQuerySingle(conn,SELECTSEQ,new Object[]{tmpDetail.askNumber,reqCJFrgCurrSingleBat.reqHeader.bankCode});
                    if(selMap.size()>0){//存在，说明是重发，取原映射请求流水
                        askNumber=selMap.get("BANKREQSEQID").toString();
                    }else {//不存在，生成符合请求要求的唯一流水号
                        askNumber=getReqId(tmpDetail.askNumber,tmpDetail.name,tmpDetail.value,tmpDetail.fieldNum);
                        //记录ats支付流水号对应的银行支付流水号，供查询状态接口使用
                        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                        JDBCHelper.update(conn, INSERTSEQ, new Object[]{uuid, reqCJFrgCurrSingleBat.reqHeader.bankCode, Format.Date8Format.format(new Date()), tmpDetail.askNumber, askNumber});
                    }
                    //================付款流水号处理end================
                    //拼接请求报文
                    xmlTextWriter.writeStartElement("PaymentInfo");
                    xmlTextWriter.writeElementStringWithoutTransfer("Id",askNumber);//批内流水
                    xmlTextWriter.writeStartElement("Fields");
                    xmlTextWriter.writeStartElement("Field");
                    xmlTextWriter.writeElementStringWithoutTransfer("Name","TemplateName");//模板名称
                    xmlTextWriter.writeElementStringWithoutTransfer("Value",tmpDetail.templateName);//模板名称
                    xmlTextWriter.writeEndElement();
                    String[] flag=xmlTextWriterBody(xmlTextWriter,tmpDetail.name,tmpDetail.value,tmpDetail.fieldNum);
                    if(!"0".equals(flag[0])){
                        WriteBankLogLn(flag[1]);
                        retAts.respCode = "-1";
                        retAts.respInfo = flag[1];
                        retAts.writeRetToATS();
                        return retAts;
                    }
                }
                xmlTextWriter.writeEndElement();
                xmlTextWriter.writeEndElement();
                count++;
            }
            if(count!=Integer.parseInt(reqCJFrgCurrSingleBat.totalNum)){
                WriteBankLogLn("DetailRecord总数据与RecordNum不一致");
                retAts.respCode = "-1";
                retAts.respInfo = "DetailRecord总数据与RecordNum不一致";
                retAts.writeRetToATS();
                return retAts;
            }
            xmlTextWriter.writeEndElement();
            xmlTextWriter.writeEndElement();
            //获取Request
            String requestContent=getRequestXml(xmlTextWriter.toXmlString());
            //签名
            xmlTextWriter.writeElementStringWithoutTransfer("APPID",getBankConfig().getValueAsString("appId"));//appid
            xmlTextWriter.writeElementStringWithoutTransfer("SIGNATURE",signXml(requestContent,"Request",getBankConfig().getValueAsString("secret"),getCharset()));//签名
            xmlTextWriter.writeEndDocument();
            //发送请求报文
            String[] tmpStrRet = sendToBank(xmlTextWriter.toXmlString(),"swift");

            //处理响应报文
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    //获取Response
                    String reqContentXml=tmpBkReader.getOuterXml("/Document/Response");
                    //获取签名数据
                    String signedHex=tmpBkReader.getFirstText("/Document/SIGNATURE");
                    //验签
                    boolean flag=verifyXmlSign(signedHex,reqContentXml,"Response",getBankConfig().getValueAsString("secret"),getCharset());
                    if(flag){
                        WriteBankLogLn("响应报文验签成功，开始处理响应报文");
                        String returnCode = tmpBkReader.getFirstText("/Document/Response/GrpHdr/ResponseStatus").trim();//返回码
                        String returnMsg = tmpBkReader.getFirstText("/Document/Response/GrpHdr/AddtlInf");//返回信息
                        retAts.respCode = "0";
                        retAts.respInfo=returnMsg;
                        retAts.reqSeqID = reqCJFrgCurrSingleBat.reqBatchNO;
                        retAts.transState = returnCode;
                        retAts.payInfoCode = retAts.transState;
                        StringBuilder sbd=new StringBuilder(" ");
                        while (tmpBkReader.read("/Document/Response/Rpt/PaymentInfo")){
                            String transState=tmpBkReader.readedXElement.getSingleTextNotNull("PaymentStatus");
                            sbd.append(tmpBkReader.readedXElement.getSingleTextNotNull("Id")).append(" ");
                            sbd.append(tmpBkReader.readedXElement.getSingleTextNotNull("Msg")).append(" ");
                            if("ERRO".equals(transState)){
                                if(tmpBkReader.readedXElement.getSingleChild("Fields")!=null){
                                    List<XElement> xmlTextWriters=tmpBkReader.readedXElement.getSingleChild("Fields").getChildList("Field");
                                    if(xmlTextWriters!=null && xmlTextWriters.size()>0){
                                        for(XElement xElement:xmlTextWriters){
                                            sbd.append(xElement.getSingleTextNotNull("Msg")).append(",");
                                        }
                                    }
                                    sbd.deleteCharAt(sbd.length()-1).toString();
                                }
                            }
                        }
                        retAts.respInfo=retAts.respInfo+sbd;
                    }else {
                        retAts.respCode = "0";
                        retAts.respInfo = "Response数据【"+reqContentXml+"】签名【"+signedHex+"】验证失败";
                        retAts.reqSeqID = reqCJFrgCurrSingleBat.reqBatchNO;
                        retAts.transState = PaymentState.FAIL_Batch;
                        retAts.payInfoCode = retAts.transState;
                    }
                } else {
                    retAts.reqSeqID = reqCJFrgCurrSingleBat.reqBatchNO;
                    retAts.respCode = "0";
                    retAts.respInfo = tmpStrRet[1];
                    retAts.transState = PaymentState.FAIL_Batch;
                    retAts.payInfoCode = retAts.transState;
                }
            }else{
                retAts.reqSeqID = reqCJFrgCurrSingleBat.reqBatchNO;
                retAts.respCode = "0";
                retAts.respInfo = tmpStrRet[1];
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = retAts.transState;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn("付款异常："+ex);
        }finally {
            conn.close();
        }
        if (retAts.respCode.equals("-1") && StringHelper.isNullOrEmpty(retAts.reqSeqID)) {
            retAts.reqSeqID = reqCJFrgCurrSingleBat.reqBatchNO;
        }
        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * 付款状态查询
     * @param reqQryCJFrgCurrSingleBat
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsCJFrgCurrSingleBat qryForeignCurrPayCJ_BAT(ReqQryCJFrgCurrSingleBat reqQryCJFrgCurrSingleBat) throws Exception {
        RetAtsCJFrgCurrSingleBat retAts=new RetAtsCJFrgCurrSingleBat(reqQryCJFrgCurrSingleBat.reqHeader);
        Connection conn= FGBiz.getLocalDbConn();
        try{
            //非公有参数
            XmlTextWriter xmlTextWriter = new XmlTextWriter();
            //拼接请求报文头
            JRTT01Header header=new JRTT01Header();
            header.requestType="query.002.001.03";//交易码
            header.msgId=getQryTransID();
            writeCommonHeader(xmlTextWriter,header);
            xmlTextWriter.writeEndElement();
            //拼接请求报文体
            xmlTextWriter.writeStartElement("ReqDetail");
            //拼接请求报文体
            while (reqQryCJFrgCurrSingleBat.readRecord()) {
                xmlTextWriter.writeStartElement("PaymentInfo");
                Map<String, Object> selMap=JDBCHelper.execQuerySingle(conn,SELECTSEQ,new Object[]{reqQryCJFrgCurrSingleBat.readedDetail.askNumber,reqQryCJFrgCurrSingleBat.reqHeader.bankCode});
                if(selMap.size()>0){
                    xmlTextWriter.writeElementStringWithoutTransfer("Id",selMap.get("BANKREQSEQID").toString());//批内流水
                }else {
                    xmlTextWriter.writeElementStringWithoutTransfer("Id",reqQryCJFrgCurrSingleBat.readedDetail.askNumber);//批内流水
                }
                xmlTextWriter.writeElementStringWithoutTransfer("BankType",reqQryCJFrgCurrSingleBat.readedDetail.bankType);//银行类型
                xmlTextWriter.writeElementStringWithoutTransfer("PayAccount",reqQryCJFrgCurrSingleBat.readedDetail.payAct);//付方账号
                xmlTextWriter.writeElementStringWithoutTransfer("PayBankSwiftCode",reqQryCJFrgCurrSingleBat.readedDetail.paySWIFTCODE);//付方银行swifitCode
                xmlTextWriter.writeEndElement();
            }
            xmlTextWriter.writeEndElement();
            xmlTextWriter.writeEndElement();
            //获取Request
            String requestContent=getRequestXml(xmlTextWriter.toXmlString());
            //签名
            xmlTextWriter.writeElementStringWithoutTransfer("APPID",getBankConfig().getValueAsString("appId"));//appid
            xmlTextWriter.writeElementStringWithoutTransfer("SIGNATURE",signXml(requestContent,"Request",getBankConfig().getValueAsString("secret"),getCharset()));//签名
            xmlTextWriter.writeEndDocument();
            //发送请求报文
            String[] tmpStrRet = sendToBank(xmlTextWriter.toXmlString(),"swift");
            //处理报文
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    //获取Response
                    String reqContentXml=tmpBkReader.getOuterXml("/Document/Response");
                    //获取签名数据
                    String signedHex=tmpBkReader.getFirstText("/Document/SIGNATURE");
                    //验签
                    boolean flag=verifyXmlSign(signedHex,reqContentXml,"Response",getBankConfig().getValueAsString("secret"),getCharset());
                    if(flag) {
                        String returnCode = tmpBkReader.getFirstText("/Document/Response/GrpHdr/ResponseStatus").trim();//返回码
                        String returnMsg = tmpBkReader.getFirstText("/Document/Response/GrpHdr/AddtlInf");//返回信息
                        if ("ACCP".equals(returnCode)) {
                            retAts.batRespCode = "0";
                            retAts.batRespInfo = returnMsg;
                            while (tmpBkReader.read("/Document/Response/Rpt/PaymentInfo")) {
                                RetAtsCJFrgCurrSingleDetail retAtsCheckDetail = new RetAtsCJFrgCurrSingleDetail();
                                String msgMiddle = tmpBkReader.readedXElement.getSingleTextNotNull("MsgMiddle");//中间件返回消息
                                String msgFile = tmpBkReader.readedXElement.getSingleTextNotNull("MsgFile");//中间件返回消息
                                String msgInst = tmpBkReader.readedXElement.getSingleTextNotNull("MsgInst");//中间件返回消息
                                if(StringHelper.hasAnyChar(tmpBkReader.readedXElement.getSingleTextNotNull("Id"))){
                                    Map<String, Object> selMapToAts=JDBCHelper.execQuerySingle(conn,SELECTSEQ2,new Object[]{tmpBkReader.readedXElement.getSingleTextNotNull("Id").trim(),reqQryCJFrgCurrSingleBat.reqHeader.bankCode});
                                    if(selMapToAts.size()>0){
                                        retAtsCheckDetail.reqSeqID = selMapToAts.get("REQSEQID").toString();
                                    }else {
                                        retAtsCheckDetail.reqSeqID = tmpBkReader.readedXElement.getSingleTextNotNull("Id").trim();
                                    }
                                    retAtsCheckDetail.outTransID = tmpBkReader.readedXElement.getSingleTextNotNull("Id").trim();
                                    retAtsCheckDetail.respCode = "0";
                                    retAtsCheckDetail.respInfo = returnMsg+" "+msgMiddle + " " + msgFile + " " + msgInst;
                                    retAtsCheckDetail.transState = tmpBkReader.readedXElement.getSingleTextNotNull("PaymentStatus").trim();//付款状态
                                    retAtsCheckDetail.payInfoCode = retAtsCheckDetail.transState;
                                    retAtsCheckDetail.resendFlag = getBankConfig().getMapValueByKey("resendFlagMapping", retAtsCheckDetail.transState);
                                    retAts.writeRetDetail(retAtsCheckDetail);
                                }
                            }
                        }else {
                            retAts.batRespCode="-1";
                            retAts.batRespInfo=returnMsg;
                        }
                    }else {
                        retAts.batRespCode = "-1";
                        retAts.batRespInfo = "Response数据【"+reqContentXml+"】签名【"+signedHex+"】验证失败";
                    }
                } else {
                    retAts.batRespCode = "-1";
                    retAts.batRespInfo = tmpSbMsg.toString();
                }
            } else {
                retAts.batRespCode = "-1";
                retAts.batRespInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.batRespCode = "-1";
            retAts.batRespInfo = ex.getMessage();
            WriteBankLogLn("付款状态查询异常："+ex);
        }finally {
            conn.close();
        }
        retAts.writeAfterDetail();
        return retAts;
    }
}
